home *** CD-ROM | disk | FTP | other *** search
/ Collection of Internet / Collection of Internet.iso / infosrvr / dev / scott / WWW / NextStep / Implementation / StyleToy.m < prev    next >
Text File  |  1993-07-06  |  9KB  |  367 lines

  1. /*    Style Toy:    Allows user manipulation of styles    StyleToy.m
  2. **    ---------    ----------------------------------
  3. */
  4.  
  5. #import "StyleToy.h"
  6. #import "HTParse.h"
  7. #import "HTStyle.h"
  8. #import "HTUtils.h"
  9.  
  10. #import "HyperText.h"
  11. #define THIS_TEXT  (HyperText *)[[[NXApp mainWindow] contentView] docView]
  12.  
  13. /*    Field numbers in the parameter form:
  14. */
  15. #define    SGMLTAG_FIELD        4
  16. #define FONT_NAME_FIELD        2
  17. #define FONT_SIZE_FIELD        3
  18. #define FIRST_INDENT_FIELD    0
  19. #define    SECOND_INDENT_FIELD    1
  20.  
  21. @implementation StyleToy
  22.  
  23. extern char * appDirectory;        /* Pointer to directory for application */
  24.  
  25. //    Global styleSheet available to every one:
  26.  
  27.        HTStyleSheet * styleSheet = 0;
  28.  
  29. static HTStyle * style;            /* Current Style */
  30. static OpenPanel * open_panel;        /* Keep the open panel alive */
  31. static SavePanel * save_panel;        /* Keep a Save panel too */
  32.  
  33. //    Create new one:
  34.  
  35. + new
  36. {
  37.     self = [super new];
  38.     [self loadDefaultStyleSheet];
  39.     return self;
  40. }
  41.  
  42. //    Set connections to other objects:
  43.  
  44. - setTabForm:anObject
  45. {
  46.     TabForm = anObject;
  47.     return self;
  48. }
  49.  
  50. - setParameterForm:anObject
  51. {
  52.     ParameterForm = anObject;
  53.     return self;
  54. }
  55.  
  56. - setStylePanel:anObject
  57. {
  58.     StylePanel = anObject;
  59.     return self;
  60. }
  61.  
  62. - setNameForm:anObject
  63. {
  64.     NameForm = anObject;
  65.     return self;
  66. }
  67.  
  68.  
  69. //            ACTION METHODS
  70. //            ==============
  71.  
  72. //    Display style in the panel
  73.  
  74. - display_style
  75. {
  76.     if(style->name) [NameForm setStringValue:style->name at:0];
  77.     else [NameForm setStringValue:"" at:0];
  78.     
  79.     if(style->SGMLTag) [ParameterForm setStringValue:style->SGMLTag at:SGMLTAG_FIELD];
  80.     else [ParameterForm setStringValue:"" at:SGMLTAG_FIELD];
  81.     
  82.     [ParameterForm setStringValue:[style->font name] at:FONT_NAME_FIELD];
  83.  
  84.     [ParameterForm setFloatValue:style->fontSize at:FONT_SIZE_FIELD];
  85.     
  86.     if(style->paragraph) {
  87.         char tabstring[255];
  88.     int i;
  89.            [ParameterForm setFloatValue:style->paragraph->indent1st
  90.                        at:FIRST_INDENT_FIELD];
  91.         [ParameterForm setFloatValue:style->paragraph->indent2nd 
  92.                 at:SECOND_INDENT_FIELD];
  93.     tabstring[0]=0;
  94.     for(i=0; i < style->paragraph->numTabs; i++) {
  95.         sprintf(tabstring+strlen(tabstring), "%.0f ", style->paragraph->tabs[i].x);
  96.     }
  97.     [TabForm setStringValue:tabstring at:0];
  98.     }     
  99.     return self;
  100. }
  101.  
  102.  
  103. //    Load style from Panel
  104. //
  105. //    @@ Tabs not loaded
  106.  
  107. -load_style
  108. {
  109.     char * name = 0;
  110.     char * stripped;
  111.     
  112.     style->fontSize=[ParameterForm floatValueAt:FONT_SIZE_FIELD];
  113.     StrAllocCopy(name, [NameForm stringValueAt:0]);
  114.     stripped = HTStrip(name);
  115.     if (*stripped) {
  116.         id font;
  117.     font = [Font newFont:stripped size:style->fontSize];
  118.     if (font) style->font = font;
  119.     }
  120.     free(name);
  121.     name = 0;
  122.     
  123.     StrAllocCopy(name, [ParameterForm stringValueAt:SGMLTAG_FIELD]);
  124.     stripped = HTStrip(name);
  125.     if (*stripped) {
  126.         StrAllocCopy(style->SGMLTag, stripped);
  127.     }
  128.     free(name);
  129.     name = 0;
  130.     
  131.     if (!style->paragraph) style->paragraph = malloc(sizeof(*(style->paragraph)));
  132.     style->paragraph->indent1st = [ParameterForm floatValueAt: FIRST_INDENT_FIELD];
  133.     style->paragraph->indent2nd = [ParameterForm floatValueAt: SECOND_INDENT_FIELD];
  134.  
  135.     return self;
  136. }
  137.  
  138.  
  139. //    Open a style sheet from a file
  140. //    ------------------------------
  141. //
  142. //    We overlay any previously defined styles with new ones, but leave
  143. //    old ones which are not redefined.
  144.  
  145. - open:sender
  146. {  
  147.     NXStream * s;            //    The file stream
  148.     const char * filename;        //    The name of the file
  149.     char *typelist[2] = {"style",(char *)0};    //    Extension must be ".style."
  150.  
  151.     if (!open_panel) {
  152.         open_panel = [OpenPanel new];
  153.         [open_panel allowMultipleFiles:NO];
  154.     }
  155.     
  156.     if (![open_panel runModalForTypes:typelist]) {
  157.         if (TRACE) printf("No file selected.\n");
  158.     return nil;
  159.     }
  160.  
  161.     filename = [open_panel filename];
  162.     s = NXMapFile(filename, NX_READONLY);
  163.     if (!s) {
  164.         if(TRACE) printf("Styles: Can't open file %s\n", filename);
  165.         return nil;
  166.     }
  167.     if (!styleSheet) styleSheet = HTStyleSheetNew();
  168.     StrAllocCopy(styleSheet->name, filename);
  169.     if (TRACE) printf("Stylesheet: New one called %s.\n", styleSheet->name);
  170.     (void)HTStyleSheetRead(styleSheet, s);
  171.     NXCloseMemory(s, NX_FREEBUFFER);
  172.     style = styleSheet->styles;
  173.     [self display_style];
  174.     return self;
  175. }
  176.  
  177.  
  178. //    Load default style sheet
  179. //    ------------------------
  180. //
  181. //    We load EITHER the user's style sheet (if it exists) OR the system one.
  182. //    This saves a bit of time on load. An alternative would be to load the
  183. //    system style sheet and then overload the styles in the user's, so that
  184. //    he could redefine a subset only of the styles.
  185. //    If the HOME directory is defined, then it is always used a the
  186. //    style sheet name, so that any changes will be saved in the user's
  187. //    $(HOME)/WWW directory.
  188.  
  189. - loadDefaultStyleSheet
  190. {
  191.     NXStream * stream;
  192.     
  193.     if (!styleSheet) styleSheet = HTStyleSheetNew();
  194.     styleSheet->name = malloc(strlen(appDirectory)+13+1);
  195.     strcpy(styleSheet->name, appDirectory);
  196.     strcat(styleSheet->name, "default.style");
  197.  
  198.     if (getenv("HOME")) {
  199.         char name[256];
  200.     strcpy(name, getenv("HOME"));
  201.     strcat(name, "/WWW/default.style");
  202.         StrAllocCopy(styleSheet->name, name);
  203.         stream = NXMapFile(name, NX_READONLY);
  204.     } else stream = 0;
  205.  
  206.     if (!stream) {
  207.         char name[256];
  208.     strcpy(name, appDirectory);
  209.     strcat(name, "default.style");
  210.         if (TRACE) printf("Couldn't open $(HOME)/WWW/default.style\n");
  211.     stream = NXMapFile(name, NX_READONLY);
  212.     if (!stream)
  213.         printf("Couldn't open %s, errno=%i\n", name, errno);
  214.     }
  215.     
  216.     if (stream) {
  217.     (void)HTStyleSheetRead(styleSheet, stream);
  218.     NXCloseMemory(stream, NX_FREEBUFFER);
  219.     style = styleSheet->styles;
  220.     [self display_style];
  221.     }
  222.     return self;
  223. }
  224.  
  225.  
  226. //    Save style sheet to a file
  227. //    --------------------------
  228.  
  229. - saveAs:sender
  230. {  
  231.     NXStream * s;            //    The file stream
  232.     char * slash;
  233.     int status;
  234.     char * suggestion=0;        //    The name of the file to suggest
  235.     const char * filename;        //    The name chosen
  236.  
  237.     if (!save_panel) {
  238.         save_panel = [SavePanel new];    //    Keep between invocations
  239.     }
  240.     
  241.     StrAllocCopy(suggestion,styleSheet->name);
  242.     slash = rindex(suggestion, '/');    //    Point to last slash
  243.     if (slash) {
  244.         *slash++ = 0;            /* Separate directory and filename */
  245.     status = [save_panel runModalForDirectory:suggestion file:slash];
  246.     } else {
  247.     status = [save_panel runModalForDirectory:"." file:suggestion];
  248.     }
  249.     free(suggestion);
  250.     
  251.     if (!status) {
  252.         if (TRACE) printf("No file selected.\n");
  253.     return nil;
  254.     }
  255.     
  256.     filename = [save_panel filename];
  257.     s = NXMapFile(filename, NX_WRITEONLY);
  258.     if (!s) {
  259.         if(TRACE) printf("Styles: Can't open file %s for write\n", filename);
  260.         return nil;
  261.     }
  262.     StrAllocCopy(styleSheet->name, filename);
  263.     if (TRACE) printf("StylestyleSheet: Saving as `%s'.\n", styleSheet->name);
  264.     (void)HTStyleSheetWrite(styleSheet, s);
  265.     NXSaveToFile(s, styleSheet->name);
  266.     NXCloseMemory(s, NX_FREEBUFFER);
  267.     style = styleSheet->styles;
  268.     [self display_style];
  269.     return self;
  270. }
  271.  
  272.  
  273. //    Move to next style
  274. //    ------------------
  275.  
  276. - NextButton:sender
  277. {
  278.     if (styleSheet->styles)
  279.         if (styleSheet->styles->next)
  280.             if (style->next) {
  281.             style = style->next;
  282.             } else {
  283.             style = styleSheet->styles;
  284.             }
  285.     [self display_style];
  286.     return self;
  287. }
  288.  
  289.  
  290. - FindUnstyledButton:sender
  291. {
  292.     [THIS_TEXT selectUnstyled: styleSheet];
  293.     return self;
  294. }
  295.  
  296. //    Apply current style to selection
  297. //    --------------------------------
  298.  
  299. - ApplyButton:sender
  300. {
  301.     [THIS_TEXT applyStyle:style];
  302.     return self;
  303. }
  304.  
  305. - applyStyleNamed: (const char *)name
  306. {
  307.      HTStyle * thisStyle = HTStyleNamed(styleSheet, name);
  308.      if (!thisStyle) return nil;
  309.      return [THIS_TEXT applyStyle:thisStyle];
  310. }
  311.  
  312. - heading1Button:sender    { return [self applyStyleNamed:"Heading1" ]; }
  313. - heading2Button:sender    { return [self applyStyleNamed:"Heading2" ]; }
  314. - heading3Button:sender    { return [self applyStyleNamed:"Heading3" ]; }
  315. - heading4Button:sender    { return [self applyStyleNamed:"Heading4" ]; }
  316. - heading5Button:sender    { return [self applyStyleNamed:"Heading5" ]; }
  317. - heading6Button:sender    { return [self applyStyleNamed:"Heading6" ]; }
  318. - normalButton:sender    { return [self applyStyleNamed:"Normal" ]; }
  319. - addressButton:sender    { return [self applyStyleNamed:"Address" ]; }
  320. - exampleButton:sender    { return [self applyStyleNamed:"Example" ]; }
  321. - listButton:sender    { return [self applyStyleNamed:"List" ]; }
  322. - menuButton:sender    { return [self applyStyleNamed:"Menu" ]; }
  323. - dirButton:sender    { return [self applyStyleNamed:"Dir" ]; }
  324. - glossaryButton:sender    { return [self applyStyleNamed:"Glossary" ]; }
  325.  
  326.  
  327. //    Move to previous style
  328. //    ----------------------
  329.  
  330. - PreviousButton:sender
  331. {
  332.     HTStyle * scan;
  333.     for (scan = styleSheet->styles; scan; scan=scan->next) {
  334.         if ((scan->next==style) || (scan->next==0)){
  335.         style = scan;
  336.         break;
  337.     }
  338.     }
  339.     [self display_style];
  340.     return self;
  341. }
  342.  
  343. - SetButton:sender
  344. {
  345.     [self load_style];
  346.     [THIS_TEXT updateStyle:style];
  347.     return self;
  348. }
  349.  
  350. - PickButton:sender
  351. {
  352.     HTStyle * st = [THIS_TEXT selectionStyle:styleSheet];
  353.     if (st) {
  354.         style = st;
  355.     [self display_style];
  356.     }
  357.     return self;
  358. }
  359.  
  360. - ApplyToSimilar:sender
  361. {
  362.     return [THIS_TEXT applyToSimilar:style];
  363. }
  364.  
  365.  
  366. @end
  367.